package club.bigtian.sync.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.FileCopyUtils;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Properties;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 同步配置类
 * 用于配置同步模式、表和批量大小等
 */
@Component
public class SyncConfig {

    private static final Logger log = LoggerFactory.getLogger(SyncConfig.class);

    /**
     * 同步模式：full(全量)、incremental(增量)、full_incremental(全量+增量)
     */
    @Value("${sync.mode}")
    private String syncMode;

    /**
     * 同步的表名，多个表用逗号分隔
     */
    @Value("${sync.tables:}")
    private String tableList;

    /**
     * 批量操作的大小
     */
    @Value("${sync.batch.size}")
    private int batchSize;

    /**
     * 是否启用binlog同步
     */
    @Value("${sync.binlog.enabled}")
    private boolean binlogEnabled;
    
    /**
     * binlog文件名
     */
    @Value("${sync.binlog.filename:}")
    private String binlogFilename;
    
    /**
     * binlog位置
     */
    @Value("${sync.binlog.position:0}")
    private long binlogPosition;
    
    /**
     * 上次同步的binlog文件名
     */
    @Value("${sync.binlog.last.filename:}")
    private String lastBinlogFilename;
    
    /**
     * 上次同步的binlog位置
     */
    @Value("${sync.binlog.last.position:0}")
    private long lastBinlogPosition;

    @Value("${mysql.host}")
    private String mysqlHost;

    @Value("${mysql.port}")
    private int mysqlPort;

    @Value("${mysql.username}")
    private String mysqlUsername;

    @Value("${mysql.password}")
    private String mysqlPassword;

    @Value("${mysql.database}")
    private String mysqlDatabase;

    /**
     * 是否启用全量导入
     */
    @Value("${sync.full.import.enabled}")
    private boolean fullImportEnabled;

    /**
     * 是否在创建表之前删除已有的表
     */
    @Value("${sync.delete.existing.tables:false}")
    private boolean  syncDeleteExistingTables;

    /**
     * 定时刷入磁盘的时间（秒）
     */
    @Value("${sync.disk.flush.interval:60}") // 默认值为60秒
    private int diskFlushInterval;

    private ScheduledExecutorService scheduler;

    public SyncConfig() {
        // 启动定时任务，每隔60秒保存一次配置
        if (diskFlushInterval <= 0) {
            diskFlushInterval = 60; // 设置默认值为60秒
        }
        scheduler = Executors.newScheduledThreadPool(1);
        scheduler.scheduleAtFixedRate(() -> {
            saveConfig();
        }, 0, diskFlushInterval, TimeUnit.SECONDS);
    }

    /**
     * 获取同步模式
     */
    public String getSyncMode() {
        return syncMode;
    }

    /**
     * 获取同步的表列表
     */
    public List<String> getTableList() {
        if (tableList == null || tableList.isEmpty()) {
            return getAllTables();
        }
        return Arrays.asList(tableList.split(","));
    }

    /**
     * 获取批量操作的大小
     */
    public int getBatchSize() {
        return batchSize;
    }

    /**
     * 是否启用binlog同步
     */
    public boolean isBinlogEnabled() {
        return binlogEnabled;
    }
    
    /**
     * 获取binlog文件名
     */
    public String getBinlogFilename() {
        return binlogFilename;
    }
    
    /**
     * 获取binlog位置
     */
    public long getBinlogPosition() {
        return binlogPosition;
    }
    
    /**
     * 获取上次同步的binlog文件名
     */
    public String getLastBinlogFilename() {
        return lastBinlogFilename;
    }
    
    /**
     * 获取上次同步的binlog位置
     */
    public long getLastBinlogPosition() {
        return lastBinlogPosition;
    }

    /**
     * 是否执行全量同步
     */
    public boolean isFullSync() {
        return "full".equals(syncMode) || "full_incremental".equals(syncMode);
    }

    /**
     * 是否执行增量同步
     */
    public boolean isIncrementalSync() {
        return "incremental".equals(syncMode) || "full_incremental".equals(syncMode);
    }

    /**
     * 是否启用全量导入
     */
    public boolean isFullImportEnabled() {
        return fullImportEnabled;
    }

    public String getMysqlHost() {
        return mysqlHost;
    }

    public int getMysqlPort() {
        return mysqlPort;
    }

    public String getMysqlUsername() {
        return mysqlUsername;
    }

    public String getMysqlPassword() {
        return mysqlPassword;
    }

    public String getMysqlDatabase() {
        return mysqlDatabase;
    }

    public void setMysqlHost(String mysqlHost) {
        this.mysqlHost = mysqlHost;
    }

    public void setMysqlPort(int mysqlPort) {
        this.mysqlPort = mysqlPort;
    }

    public void setMysqlUsername(String mysqlUsername) {
        this.mysqlUsername = mysqlUsername;
    }

    public void setMysqlPassword(String mysqlPassword) {
        this.mysqlPassword = mysqlPassword;
    }

    public void setMysqlDatabase(String mysqlDatabase) {
        this.mysqlDatabase = mysqlDatabase;
    }

    public void setSyncMode(String syncMode) {
        this.syncMode = syncMode;
    }

    public void setTableList(String tableList) {
        this.tableList = tableList;
    }

    public void setBatchSize(int batchSize) {
        this.batchSize = batchSize;
    }

    public void setBinlogEnabled(boolean binlogEnabled) {
        this.binlogEnabled = binlogEnabled;
    }
    
    /**
     * 设置binlog文件名
     */
    public void setBinlogFilename(String binlogFilename) {
        this.binlogFilename = binlogFilename;
    }
    
    /**
     * 设置binlog位置
     */
    public void setBinlogPosition(long binlogPosition) {
        this.binlogPosition = binlogPosition;
    }
    
    /**
     * 设置上次同步的binlog文件名
     */
    public void setLastBinlogFilename(String lastBinlogFilename) {
        this.lastBinlogFilename = lastBinlogFilename;
    }
    
    /**
     * 设置上次同步的binlog位置
     */
    public void setLastBinlogPosition(long lastBinlogPosition) {
        this.lastBinlogPosition = lastBinlogPosition;
    }

    public void setFullImportEnabled(boolean fullImportEnabled) {
        this.fullImportEnabled = fullImportEnabled;
    }

    public List<String> getAllTables() {
        if (mysqlDatabase == null || mysqlDatabase.isEmpty()) {
            throw new IllegalArgumentException("数据库名不能为空");
        }
        List<String> tables = new ArrayList<>();
        String url = "jdbc:mysql://" + mysqlHost + ":" + mysqlPort + "/" + mysqlDatabase;
        try (Connection conn = DriverManager.getConnection(url, mysqlUsername, mysqlPassword);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SHOW TABLES")) {
            while (rs.next()) {
                tables.add(rs.getString(1));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return tables;
    }

    /**
     * 从配置文件中刷新配置
     */
    public void refreshConfig() {
        try {
            Properties properties = new Properties();
            Resource resource = new ClassPathResource("application.properties");
            properties.load(resource.getInputStream());

            // 重新加载配置
            this.syncMode = properties.getProperty("sync.mode");
            this.tableList = properties.getProperty("sync.tables");
            this.batchSize = Integer.parseInt(properties.getProperty("sync.batch.size"));
            this.binlogEnabled = Boolean.parseBoolean(properties.getProperty("sync.binlog.enabled"));
            this.binlogFilename = properties.getProperty("sync.binlog.filename");
            this.binlogPosition = Long.parseLong(properties.getProperty("sync.binlog.position"));
            this.lastBinlogFilename = properties.getProperty("sync.binlog.last.filename");
            this.lastBinlogPosition = Long.parseLong(properties.getProperty("sync.binlog.last.position"));
            this.mysqlHost = properties.getProperty("mysql.host");
            this.mysqlPort = Integer.parseInt(properties.getProperty("mysql.port"));
            this.mysqlUsername = properties.getProperty("mysql.username");
            this.mysqlPassword = properties.getProperty("mysql.password");
            this.mysqlDatabase = properties.getProperty("mysql.database");
            this.fullImportEnabled = Boolean.parseBoolean(properties.getProperty("sync.full.import.enabled"));
            this.syncDeleteExistingTables = Boolean.parseBoolean(properties.getProperty("sync.delete.existing.tables"));
            this.diskFlushInterval = Integer.parseInt(properties.getProperty("sync.disk.flush.interval", "60"));

            log.info("配置已从application.properties文件中刷新");
        } catch (Exception e) {
            log.error("刷新配置失败: {}", e.getMessage(), e);
        }
    }

    public void updateDiskFlushInterval() {
        // 停止当前的调度任务
        scheduler.shutdown();
        // 重新创建调度器
        scheduler = Executors.newScheduledThreadPool(1);
        // 启动新的定时任务
        scheduler.scheduleAtFixedRate(() -> {
            saveConfig();
        }, 0, diskFlushInterval, TimeUnit.SECONDS);
    }

    public CompletableFuture<Void> saveConfig() {
        return CompletableFuture.runAsync(() -> {
            Properties properties = new Properties();
            properties.setProperty("sync.mode", syncMode);
            properties.setProperty("sync.tables", tableList);
            properties.setProperty("sync.batch.size", String.valueOf(batchSize));
            properties.setProperty("sync.binlog.enabled", String.valueOf(binlogEnabled));
            properties.setProperty("sync.binlog.filename", binlogFilename);
            properties.setProperty("sync.binlog.position", String.valueOf(binlogPosition));
            properties.setProperty("sync.binlog.last.filename", lastBinlogFilename);
            properties.setProperty("sync.binlog.last.position", String.valueOf(lastBinlogPosition));
            properties.setProperty("mysql.host", mysqlHost);
            properties.setProperty("mysql.port", String.valueOf(mysqlPort));
            properties.setProperty("mysql.username", mysqlUsername);
            properties.setProperty("mysql.password", mysqlPassword);
            properties.setProperty("mysql.database", mysqlDatabase);
            properties.setProperty("sync.full.import.enabled", String.valueOf(fullImportEnabled));
            properties.setProperty("sync.drop.table.before.create", String.valueOf(syncDeleteExistingTables));
            properties.setProperty("sync.disk.flush.interval", String.valueOf(diskFlushInterval));

            try {
                properties.store(Files.newOutputStream(Paths.get("config/application.properties")), null);
                log.info("配置已保存到application.properties文件");

            } catch (IOException e) {
                log.error("保存配置到文件失败: {}", e.getMessage(), e);
            }
        });
    }

    public boolean isSyncDeleteExistingTables() {
        return syncDeleteExistingTables;
    }

    public void setSyncDeleteExistingTables(boolean syncDeleteExistingTables) {
        this.syncDeleteExistingTables = syncDeleteExistingTables;
    }

    public int getDiskFlushInterval() {
        return diskFlushInterval;
    }

    public void setDiskFlushInterval(int diskFlushInterval) {
        this.diskFlushInterval = diskFlushInterval;
    }
}